package com.we.es.client;

import java.lang.reflect.Field;
import java.util.List;

import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.Requests;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.DeleteByQueryAction;
import org.nutz.log.Log;
import org.nutz.log.Logs;

import com.uxuexi.core.common.util.ExceptionUtil;
import com.uxuexi.core.common.util.Util;
import com.we.es.entity.EsIndexEntity;
import com.we.es.support.ElaticSearchHelper;
import com.we.es.support.IndexHelper;
import com.we.es.util.ReflectionUtil;

/**
 * 提供创建索引和删除索引相关的方法
 * 
 * @author 朱晓川
 */
public class EsIndexUtil {

	static final Log log = Logs.get();

	/**
	 * 
	 * 创建一条索引
	 * <p>
	 * 如果是常规索引，则不对属性名做任何处理,如果是动态索引,属性名会加上额外的后缀,用于匹配预先定义的动态模板.
	 * 
	 * @param type 索引类型
	 * @param entity  实体对象
	 * @param isNormal 是否常规实体
	 */
	public static IndexResponse addIndex(final EsIndexEntity entity) {
		// 取得对象的所有字段
		Field[] fields = ReflectionUtil.getFields(entity);
		if (Util.isEmpty(fields)) {
			return null;
		}

		try {
			TransportClient client = ElaticSearchHelper.getClient();
			XContentBuilder source = IndexHelper.getScource(entity);
			String indexName = entity.getIndexName();
			IndexResponse response = client.prepareIndex(indexName, IndexHelper.DEFAULT_TYPE).setSource(source).get();
			return response;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 批量索引数据
	 */
	public static BulkResponse addIndex(List<? extends EsIndexEntity> entitys) {
		BulkRequest req = Requests.bulkRequest();
		//提交完以后刷新
		req.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);

		TransportClient client = ElaticSearchHelper.getClient();
		for (EsIndexEntity entity : entitys) {
			XContentBuilder source = IndexHelper.getScource(entity);
			IndexRequestBuilder indexReq = client.prepareIndex(entity.getIndexName(), IndexHelper.DEFAULT_TYPE)//  
					.setSource(source);
			req.add(indexReq.request());
		}
		return client.bulk(req).actionGet();
	}

	/**
	 * 按照id更新
	 */
	public static UpdateResponse updateById(EsIndexEntity entity) {
		String id = entity.getId();
		if (Util.isEmpty(id)) {
			return null;
		}

		try {
			String indexName = entity.getIndexName();
			UpdateRequest updateRequest = new UpdateRequest();
			updateRequest.index(indexName);
			updateRequest.type(IndexHelper.DEFAULT_TYPE);
			updateRequest.id(id);

			XContentBuilder doc = IndexHelper.getScource(entity);
			updateRequest.doc(doc);

			TransportClient client = ElaticSearchHelper.getClient();
			return client.update(updateRequest).get();
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 按照id删除
	 */
	public static void deleteById(EsIndexEntity entity) {
		String id = entity.getId();
		if (Util.isEmpty(id)) {
			return;
		}
		deleteById(id, entity.getClass());
	}

	/**
	 * 按照id删除，id为空则什么也不做
	 */
	public static void deleteById(String id, Class<? extends EsIndexEntity> clazz) {
		if (Util.isEmpty(id)) {
			return;
		}

		if (Util.isEmpty(clazz)) {
			throw ExceptionUtil.pEx("索引类型不能为空");
		}

		try {
			String indexName = clazz.newInstance().getIndexName();
			TransportClient client = ElaticSearchHelper.getClient();
			DeleteByQueryAction.INSTANCE.newRequestBuilder(client).filter(QueryBuilders.matchQuery("_id", id))
					.source(indexName).execute(new ActionListener<BulkByScrollResponse>() {
						@Override
						public void onResponse(BulkByScrollResponse response) {
							//do nothing
						}

						@Override
						public void onFailure(Exception e) {
							log.debug("删除失败", e);
						}
					});
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 是否存在索引库
	 * 
	 * @param indexName
	 * @return
	 */
	public static boolean existsIndex(String indexName) {
		IndicesExistsRequest request = new IndicesExistsRequest(indexName);
		return ElaticSearchHelper.getClient().admin().indices().exists(request).actionGet().isExists();
	}

	/**
	 * 删除索引库 慎用
	 * @param indexName
	 */
	public static void dropIndex(String indexName) {
		if (existsIndex(indexName)) {
			DeleteIndexRequest request = new DeleteIndexRequest(indexName);
			ElaticSearchHelper.getClient().admin().indices().delete(request);
		}
	}
}